package com.hu.common.util.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hu.common.domain.base.ActionResultCode;
import com.hu.common.domain.base.AuthorizeUrlVO;
import com.hu.common.domain.base.UserInfo;
import com.hu.common.model.OnlineUserModel;
import com.hu.common.model.OnlineUserProvider;
import com.hu.common.model.PwdBlackListVO;
import com.hu.common.util.DateUtil;
import com.hu.common.util.adm.ServletUtil;
import com.hu.common.util.adm.StringUtil;
import com.hu.common.util.comm.CacheKeyUtil;
import com.hu.common.util.comm.JsonUtil;
import com.hu.common.util.comm.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author RDP开发平台组
 * @version V3.1.0
 * @copyright 信息技术有限公司
 * @date 2021/3/16 8:59
 */
@Component
@RequiredArgsConstructor
public class UserProvider {

    private final RedisUtil redisUtil;
    private final CacheKeyUtil cacheKeyUtil;

    /**
     * 获取token
     */
    public static String getToken() {
        String toke = getAuthorize();
        return toke;
    }

    /**
     * 获取
     *
     * @param token
     * @return
     */
    public UserInfo get(String token) {
        UserInfo userInfo = new UserInfo();
        token = JwtsUtil.getRealToken(token);
        String tokens = null;
        if (token != null) {
            tokens = token;
        } else {
            tokens = UserProvider.getToken();
            tokens = JwtsUtil.getRealToken(tokens);
        }
        if (tokens != null) {
            userInfo = JsonUtil.getJsonToBean(String.valueOf(redisUtil.getString(tokens)), UserInfo.class);
        }
        if (userInfo == null) {
            userInfo = new UserInfo();
        }
        return userInfo;
    }

    /**
     * 获取
     *
     * @return
     */
    public UserInfo get() {
        String token = UserProvider.getToken();
        return this.get(token);
    }

    /**
     * 通过上下文的租户查redis来获取token
     *
     * @return
     */
    public UserInfo get(String userId, String tenantId) {
        UserInfo userInfo;
        tenantId = "null".equals(String.valueOf(tenantId)) ? "" : tenantId;
        String token = tenantId + "login_online_" + userId;
        if (ServletUtil.getIsMobileDevice()) {
            token = tenantId + "login_online_mobile_" + userId;
        }
        String OnlineInfo = String.valueOf(redisUtil.getString(token));
        userInfo = JsonUtil.getJsonToBean(String.valueOf(redisUtil.getString(OnlineInfo)), UserInfo.class);
        return userInfo == null ? new UserInfo() : userInfo;
    }

    /**
     * 获取Authorize
     */
    public static String getAuthorize() {
        String authorize = ServletUtil.getHeader("Authorization");
        return authorize;
    }

    /**
     * 创建
     *
     * @param userInfo
     * @return
     */
    public void add(UserInfo userInfo) {
        String userId = userInfo.getUserId();
        long time = DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date());

        String authorize = String.valueOf(redisUtil.getString(cacheKeyUtil.getUserAuthorize() + userId));
        String loginOnlineKey = cacheKeyUtil.getLoginOnline() + userId;
        redisUtil.remove(authorize);
        //记录Token
        redisUtil.insert(userInfo.getId(), userInfo, time);
        //记录在线
        if (ServletUtil.getIsMobileDevice()) {
            redisUtil.insert(cacheKeyUtil.getMobileLoginOnline() + userId, userInfo.getId(), time);
            //记录移动设备CID,用于消息推送
            if (ServletUtil.getHeader("clientId") != null) {
                String clientId = ServletUtil.getHeader("clientId");
                Map<String, String> map = new HashMap<>(16);
                map.put(userInfo.getUserId(), clientId);
                redisUtil.insert(cacheKeyUtil.getMobileDeviceList(), map);
            }
        } else {
            redisUtil.insert(loginOnlineKey, userInfo.getId(), time);
        }
    }

    /**
     * 将登录用户已有url权限放入redis中
     *
     * @Author: 63691 沈韬
     * @Date: 2022/7/5 17:13
     * @Param: [userInfo]
     * @Return: void
     */
    public void addUrls(UserInfo userInfo, List<String> urls, List<String> whiteListUrls) {
        String authorizeUrlsKey = cacheKeyUtil.getUserAuthorizeUrl() + userInfo.getUserId();
        //List<String> authorizeUrls = JsonUtil.getJsonToList(redisUtil.getString(),String.class);
        redisUtil.remove(authorizeUrlsKey);
        AuthorizeUrlVO authorizeUrlVO = new AuthorizeUrlVO();
        authorizeUrlVO.setUrls(urls);
        authorizeUrlVO.setWhiteListUrls(whiteListUrls);
        long time = DateUtil.getTime(userInfo.getOverdueTime()) - DateUtil.getTime(new Date());
        //记录用户已授权urls
        redisUtil.insert(authorizeUrlsKey, authorizeUrlVO, time);
    }

    /**
     * 移除在线
     */
    public void removeWebSocket(UserInfo userInfo) {
        //清除websocket登录状态
        boolean isMobileDevice = ServletUtil.getIsMobileDevice();
        String userId = String.valueOf(userInfo.getUserId());
        String tenandId = "null".equals(String.valueOf(userInfo.getTenantId())) ? "" : userInfo.getTenantId();
        OnlineUserModel user = OnlineUserProvider.getOnlineUserList().stream().filter(t -> userId.equals(t.getUserId()) && tenandId.equals(t.getTenantId()) && isMobileDevice == t.getIsMobileDevice()).findFirst().orElse(null);
        if (user != null) {
            JSONObject object = new JSONObject();
            object.put("method", "logout");
            object.put("msg", ActionResultCode.SessionOffLine.getMessage());
            user.getWebSocket().getAsyncRemote().sendText(object.toJSONString());
        }
    }


    /**
     * 移除
     */
    public void remove() {
        UserInfo userInfo = this.get();
        String userId = userInfo.getUserId();

        if (ServletUtil.getIsMobileDevice()) {
            redisUtil.removeHash(cacheKeyUtil.getMobileDeviceList(), userId);
        }
        if (userInfo.getId() != null) {
            redisUtil.remove(userInfo.getId());
        }
        redisUtil.remove(cacheKeyUtil.getUserAuthorize() + userId);
        redisUtil.remove(cacheKeyUtil.getLoginOnline() + userId);
        redisUtil.remove(cacheKeyUtil.getSystemInfo());
    }

    /**
     * 移除当前登陆人的token
     */
    public void removeCurrent() {
        UserInfo userInfo = this.get();
        String userId = userInfo.getUserId();
        if (ServletUtil.getIsMobileDevice()) {
            String key = String.valueOf(redisUtil.getString(cacheKeyUtil.getMobileLoginOnline() + userInfo.getUserId()));
            redisUtil.remove(key);
            redisUtil.remove(cacheKeyUtil.getMobileLoginOnline() + userInfo.getUserId());
        } else {
            String key = String.valueOf(redisUtil.getString(cacheKeyUtil.getLoginOnline() + userInfo.getUserId()));
            redisUtil.remove(key);
            redisUtil.remove(cacheKeyUtil.getLoginOnline() + userInfo.getUserId());
        }
        redisUtil.remove(cacheKeyUtil.getUserAuthorize() + userId);
        redisUtil.remove(cacheKeyUtil.getUserAuthorizeUrl() + userId);
        redisUtil.remove(cacheKeyUtil.getSystemInfo());
    }

    /**
     * 移除在线
     */
    public void removeOnLine(String userId) {

        if (userId == null) {
            return;
        }
        String onlineToken = String.valueOf(redisUtil.getString(cacheKeyUtil.getLoginOnline() + userId));
        String mobileOnlineToken = String.valueOf(redisUtil.getString(cacheKeyUtil.getMobileLoginOnline() + userId));
        if (!StringUtils.isEmpty(onlineToken)) {
            redisUtil.remove(cacheKeyUtil.getLoginOnline() + userId);
            redisUtil.remove(onlineToken);
        }
        if (!StringUtils.isEmpty(mobileOnlineToken)) {
            redisUtil.remove(cacheKeyUtil.getMobileLoginOnline() + userId);
            redisUtil.removeHash(cacheKeyUtil.getMobileDeviceList(), userId);
        }
    }

    /**
     * 是否在线
     */
    public boolean isOnLine() {
        UserInfo userInfo = this.get();
        String online;
        if (ServletUtil.getIsMobileDevice()) {
            online = userInfo.getTenantId() + "login_online_mobile_" + userInfo.getUserId();
        } else {
            online = userInfo.getTenantId() + "login_online_" + userInfo.getUserId();
        }
        //判断是否在线
        if (redisUtil.exists(online)) {
            //判断在线的token是否正确
            if (userInfo.getId().equals(redisUtil.getString(online).toString())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否过期
     */
    public boolean isOverdue() {
        UserInfo userInfo = this.get();
        return StringUtil.isEmpty(userInfo.getId()) ? false : true;
    }

    /**
     * 是否登陆
     */
    public boolean isLogined() {

        UserInfo userInfo = this.get();
        String userOnline = (ServletUtil.getIsMobileDevice() == true ? cacheKeyUtil.getMobileLoginOnline() : cacheKeyUtil.getLoginOnline()) + userInfo.getUserId();
        Object online = redisUtil.getString(userOnline);
        return online == null ? true : false;
    }

    public AuthorizeUrlVO getUrls(UserInfo userInfo) {
        List<String> urls = new ArrayList<>();
        String authorizeUrlsKey = cacheKeyUtil.getUserAuthorizeUrl() + userInfo.getUserId();
        AuthorizeUrlVO authorizeUrlVO = JsonUtil.getJsonToBean(String.valueOf(redisUtil.getString(authorizeUrlsKey)), AuthorizeUrlVO.class);
    /*    if(authorizeUrlVO != null){
            urls.addAll(authorizeUrlVO.getUrls());
        }*/
        return authorizeUrlVO;
    }

    /**
     * 校验用户缓存是否存在
     */
    public UserInfo checkCurrentUser() {
        String token = getAuthorize();
        UserInfo userInfo = new UserInfo();
        token = JwtsUtil.getRealToken(token);
        if (token != null) {
            userInfo = JsonUtil.getJsonToBean(String.valueOf(redisUtil.getString(token)), UserInfo.class);
        }
        return userInfo;
    }

    /**
     * 将用户重置密码生成的唯一码放入redis
     *
     * @Author: 63691 沈韬
     * @Date: 2022/7/5 17:13
     * @Param: [userInfo]
     * @Return: void
     */
    public void creatResetPasswordCheckCode(String key, String checkCode) {
        String checkCodeKey = cacheKeyUtil.getResetPasswordCheckCode() + key;
        //List<String> authorizeUrls = JsonUtil.getJsonToList(redisUtil.getString(),String.class);
        redisUtil.remove(checkCodeKey);
        //记录用户已授权urls
        redisUtil.insert(checkCodeKey, checkCode, 600);
    }

    /**
     * 将用户重置密码生成的唯一码放入redis
     *
     * @Author: 63691 沈韬
     * @Date: 2022/7/5 17:13
     * @Param: [userInfo]
     * @Return: void
     */
    public String getResetPasswordCheckCode(String key) {
        String checkCodeKey = cacheKeyUtil.getResetPasswordCheckCode() + key;
      /*  Object value = redisUtil.getString(checkCodeKey);
        return value == null ? null : value.toString();*/
        return redisUtil.getString(checkCodeKey).toString();
    }



    /**
     * 将特征弱密码存入redis
     * @Author: 63691 沈韬
     * @Date: 2023/7/28 14:37
     * @Param: [list]
     * @Return: void
     */
    public void addPwdBlackList(List<PwdBlackListVO> list) {
        String pwdBlackKey = cacheKeyUtil.getPwdBlack();
        redisUtil.remove(pwdBlackKey);
        String pwdBlackList = JSON.toJSONString(list);
        //添加特征弱密码
        redisUtil.insert(pwdBlackKey, pwdBlackList);
    }

    /**
     * 将特征弱密码存入redis
     * @Author: 63691 沈韬
     * @Date: 2023/7/28 14:37
     * @Param: [list]
     * @Return: void
     */
    public List<PwdBlackListVO> getPwdBlackList() {
        String pwdBlackKey = cacheKeyUtil.getPwdBlack();
        Object redisObject = redisUtil.getString(pwdBlackKey);
        List<PwdBlackListVO> pwdBlackList = JsonUtil.getJsonToList(String.valueOf(redisObject), PwdBlackListVO.class);
        return pwdBlackList;
    }

}
